package token

import (
	"time"

	"github.com/google/uuid"
	"github.com/infraboard/mcube/v2/exception"
	"github.com/infraboard/mcube/v2/tools/pretty"
)

func NewToken(refUserId string) *Token {
	aExpire := time.Now().AddDate(0, 0, 1)
	rExpire := time.Now().AddDate(0, 0, 7)
	return &Token{
		RefUserId:            refUserId,
		AccessToken:          uuid.NewString(),
		AccessTokenexpireAt:  &aExpire,
		IssueTokenAt:         time.Now(),
		RefreshToken:         uuid.NewString(),
		RefreshTokenexpireAt: &rExpire,
	}
}

func (t *Token) AccessTokenTTL() int {
	if t.AccessTokenexpireAt == nil {
		return 0
	}
	return int(time.Until(*t.AccessTokenexpireAt).Seconds())
}

func (t *Token) String() string {
	return pretty.ToJSON(t)
}

type Token struct {
	// token id
	Id uint `json:"id" gorm:"primaryKey;column:id"`
	// 用户 id
	RefUserId string `json:"ref_user_id" gorm:"column:ref_user_id"`
	// token
	AccessToken string `json:"access_token" gorm:"column:access_token;unique;index"`
	// 过期时间
	AccessTokenexpireAt *time.Time `json:"access_token_expire_at" gorm:"column:access_token_expire_at"`
	// 令牌办法时间，不能为 nil
	IssueTokenAt time.Time `json:"issue_token_at" gorm:"column:issue_token_at"`
	// 登录会话保持
	// 如果客户还在使用，但是 token 过期了，用户体验会很差
	RefreshToken         string     `json:"refresh_token" gorm:"column:refresh_token;unique;index"`
	RefreshTokenexpireAt *time.Time `json:"refresh_token_expire_at" gorm:"column:refresh_token_expire_at"`
	// 关联查询，
	RefUserName string `json:"ref_user_name" gorm:"-"`
}

func (t *Token) IsAccessTokenExpired() error {
	if t.AccessTokenexpireAt == nil {
		return nil
	}
	if time.Now().After(*t.AccessTokenexpireAt) {
		return exception.NewAccessTokenExpired("%s 已过期", t.AccessToken)
	}
	return nil
}

func (t *Token) IsRefreshTokenExpired() error {
	if t.RefreshTokenexpireAt == nil {
		return nil
	}
	if time.Now().After(*t.RefreshTokenexpireAt) {
		return exception.NewAccessTokenExpired("%s 已过期", t.AccessToken)
	}
	return nil
}

func (t *Token) SetRefUserName(refUsername string) *Token {
	t.RefUserName = refUsername
	return t
}

func (t *Token) TableName() string {
	return "tokens"
}
